package admin;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Vector;

import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

import utils.Utils;

import database.IDbConnector;
import database.MySQLConnector;

import model.Params;
import model.trivial_pursuit.Card;
import model.trivial_pursuit.Theme;


/**
 * <p>Title: TP_CardModel </p>
 *
 * <p>
 * 	Description: Cette classe est le model d'une javax.swing.JTable, elle sert a peupler la Jtable
 *  la table TP_Theme de la BDD  
 * </p>
 *
 * <p>Copyright: (c) 2008 FSSIM</p>
 *
 * <p>Company: FSSImock</p>
 *
 * @author Antoine Farnault
 * @version 1.0
 */
public class TP_CardModel extends AbstractTableModel implements TableModel {

	private static final long serialVersionUID = 1L;
	private JTable tableData;
	Vector<Object> rowData = new Vector<Object>(); // Une ligne de la table
	
	private IDbConnector idbc;
	
	private Vector<String> newRow = new Vector<String>();
	private int maxId;
	
	private static final int ID_COL = 0;
	private static final int THEME_NO_COL = 1;
	private static final int THEME_COL = 2;
	private static final int COLOR_COL = 3;
	private static final int LEVEL_COL = 4;
	private static final int QUESTION_COL = 5;
	private static final int ANSWER_COL = 6;
	
	private static final Integer[] DELETERS = {ID_COL};
	private static final String DELETE_CODE = "delete";
	
	/**
	 * Remplissage de la ligne d'insertion
	 */
	private void initNewBlankRow() {
		this.newRow.add("Nouvelle carte :");	// Id
		this.newRow.add("----");		// Theme
		this.newRow.add("Nom du thème");		// Theme
		this.newRow.add("----");				// Color
		this.newRow.add(model.trivial_pursuit.TPParams.TABLE_ATTRIBUTES[1][3][3]);	// Level
		this.newRow.add("----");				// Question
		this.newRow.add("----");				// Answer
	}
	
	
	/**
	 * Consutructeur
	 */
	public TP_CardModel() {
		super();
		this.maxId = -1;
		this.maxId = -1;
		try {
			this.idbc = new MySQLConnector(Params.DB_SERVER,Params.DB_USER,Params.DB_PASSWD,Params.DB_NAME);
			this.idbc.connect();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			ResultSet rs = this.idbc.select(model.trivial_pursuit.TPParams.CARD_TABLE);
			while (rs.next()) {
				Card c = new Card(rs.getInt("id"));
				if (rs.getInt("id")>this.maxId) this.maxId=rs.getInt("id");
				rowData.add(c);
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.initNewBlankRow();
		this.newBlankRow();
	}
	
	/**
	 * Redefinition de la methode getColumnName de AbstractTableModel
	 * Elle donne automatiquement les noms des colonnes
	 * @param column le numero de colonne dont il faut le nom
	 * @return column le nom de la colonne
	 */
	@Override
	 public  String getColumnName(int column) {
         if (column==ID_COL) return "Numéro";
         if (column==THEME_NO_COL) return "N° Thème";
         if (column==THEME_COL) return "Thème";
         if (column==COLOR_COL) return "Catégorie";
         if (column==LEVEL_COL) return "Niveau";
         if (column==QUESTION_COL) return "Question";
         if (column==ANSWER_COL) return "Réponse";
         return "";
	 }

	
	/**
	 * Sauve la JTable parente
	 * @param jt : JTable parente
	 */
	public void setJTable (JTable jt) {
		this.tableData = jt;
	}
	
	/**
	 * Redefinition de la methode getColumnCount de AbstractTableModel
	 * Elle donne le nombre de colonnes de la table
	 * @return le nombre de colonne
	 */
	@Override
	public int getColumnCount() {	return 7;	}
	
	/**
	 * redefinition de la methode getRowCount de AbstractTableModel
	 * Elle donne automatiquement le nombre de lignes de la table
	 * @return le nombre de lignes
	 */
	@Override
	public int getRowCount() {	return rowData.size();	}
	/**
	 * redefinition de la methode getValueAt de AbstractTableModel
	 * Elle donne la valeur d'une cellule de la table
	 * @param i le numero de ligne
	 * @param j le numero de la colonne
	 * @return l'objet a la ligne i et colonne j
	 */
	@Override
	public Object getValueAt(int i, int j) {
//		if (i==0) return newRow.get(j);
		Object o = rowData.get(i);
		if (o instanceof Vector) {
			// 1e ligne (nouvelle entrée)
			return newRow.get(j);
		}
		if (o instanceof Card) {
			Card c = (Card) o;
			if (j == ID_COL) { return c.getId(); }
			if (j == THEME_NO_COL) { return c.getTheme(); }
			if (j == THEME_COL) {	// Theme
				try {
					Theme t = new Theme(c.getTheme());
					return t.getName();
				} catch (ClassNotFoundException e) {
					System.out.println("Impossible de se connecter à la base de données (driver JDBC non disponible)");
				} catch (SQLException e) {
					System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
				} catch (NoSuchFieldException e) {
					System.out.println("Paramètre non valide");
				}
				
			}
			if (j == COLOR_COL) { return c.getColor(); }
			if (j == LEVEL_COL) { return c.getLevel(); }
			if (j == QUESTION_COL) { return c.getQuestion(); }
			if (j == ANSWER_COL) { return c.getAnswer(); }
		}
		return "Error";
	}
	
	/**
	 * Redefinition de la méthode setValueAt de AbstractTableModel
	 * Elle enregistre la valeur entrée
	 * @param o objet à enregistrer
	 * @param i le numero de ligne
	 * @param j le numero de la colonne
	 */
	@Override
	public void setValueAt(Object o, int i, int j) {
		if (i==0) {
			this.saveNewRow(o);
			return;
		}
		String s = (String) o;
		if ( Utils.inArray( DELETERS, j) && s.equalsIgnoreCase(DELETE_CODE) ) {
			this.deleteRow(i);
			return;
		} else {
			System.out.println(DELETERS);
			System.out.println(j);
			System.out.println(s);
		}
		Card c = (Card) this.rowData.get(i);
		if (j==ID_COL) {	// Id
			//TODO : vérifier que s est libre, sinon si s<maxId ===> décaller les suivants
			try {
				c.setId(Integer.parseInt(s));
			} catch (NumberFormatException e) {
				System.out.println("Le numero doit être un entier");
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
			} catch (NoSuchFieldException e) {
				System.out.println("Paramètre non valide");
			}
			return;
		}
		if (j==THEME_NO_COL) {	// Theme #
			try {
				c.setTheme(Integer.parseInt(s));
			} catch (NumberFormatException e) {
				System.out.println("Le numero doit être un entier");
//					e.printStackTrace();
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
			} catch (NoSuchFieldException e) {
				System.out.println("Paramètre non valide");
			}
			return;
		}
		if (j==THEME_COL) {	// Theme
			try {
				c.setTheme(s);
			} catch (NumberFormatException e) {
				System.out.println("Le numero doit être un entier");
//					e.printStackTrace();
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
			} catch (NoSuchFieldException e) {
				System.out.println("Paramètre non valide");
			} catch (ClassNotFoundException e) {
				System.out.println("Impossible de se connecter à la base de données (driver JDBC non disponible)");
			}
			return;
		}
		if (j==COLOR_COL) {	// Color
			if (s.length()==0) {
				System.out.println("Couleur invalide");
				return;
			}
			if ( utils.StrUtils.checkPattern(s,"^([0-9]*)$") ) {
				try {
					c.setColor(Integer.parseInt(s));
				} catch (SQLException e) {
					System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
				} catch (NoSuchFieldException e) {
					System.out.println("Paramètre non valide");
				}
				return;
			} else {
				try {
					c.setColor(s);
				} catch (SQLException e) {
					System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
				} catch (NoSuchFieldException e) {
					System.out.println("Paramètre non valide");
				}
				return;
			}
		}
		if (j==LEVEL_COL) {	// 
			try {
				c.setLevel(Integer.parseInt(s));
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
			} catch (NoSuchFieldException e) {
				System.out.println("Paramètre non valide");
			}
			return;
		}
		if (j==QUESTION_COL) {	// 
			try {
				c.setQuestion(s);
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
			} catch (NoSuchFieldException e) {
				System.out.println("Paramètre non valide");
			}
			return;
		}
		if (j==ANSWER_COL) {	// 
			try {
				c.setAnswer(s);
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
			} catch (NoSuchFieldException e) {
				System.out.println("Paramètre non valide");
			}
			return;
		}
	}

	/**
	 * Ajout d'une ligne dans la table
	 * @param o objet à rajouter
	 */
	public void saveNewRow(Object o) {
		String s = (String) o;
//		Vector<String> row = (Vector<String>) this.rowData.get(0);
		Card c;
		if (o instanceof String) {
			try {
				c = new Card();
				Theme t = new Theme(s);
				c.create(t.getId(),1,Integer.parseInt(model.trivial_pursuit.TPParams.TABLE_ATTRIBUTES[1][3][3]),"","");
				//System.out.println("Ajout à la liste...");
				this.rowData.remove(0);
				this.rowData.add(c);
				// Création d'une nouvelle ligne
				this.newBlankRow();
			} catch (ClassNotFoundException e) {
				System.out.println("Impossible de se connecter à la base de données (driver JDBC non disponible)");
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
			} catch (NoSuchFieldException e) {
				System.out.println("Paramètre non valide");
			}
		} else {
			try {
				c = new Card();
				c.create(Integer.parseInt(s),1,Integer.parseInt(model.trivial_pursuit.TPParams.TABLE_ATTRIBUTES[1][3][3]),"","");
				//System.out.println("Ajout à la liste...");
				this.rowData.remove(0);
				this.rowData.add(c);
				// Création d'une nouvelle ligne
				this.newBlankRow();
			} catch (ClassNotFoundException e) {
				System.out.println("Impossible de se connecter à la base de données (driver JDBC non disponible)");
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
			} catch (NoSuchFieldException e) {
				System.out.println("Paramètre non valide");
			}
		}
		this.tableData.updateUI();
    }
	
	/**
	 * Crée une nouvelle ligne vide en position 0
	 */
	private void newBlankRow() {
		this.rowData.add(0,this.newRow);
	}
	
	/**
	 * Supprime la ligne i
	 * @param i ligne à supprimer
	 */
	public void deleteRow (int i) {
		Card c = (Card) this.rowData.get(i);
		try {
			c.delete();
			this.rowData.remove(i);
		} catch (NoSuchFieldException e) {
			System.out.println("Paramètre invalide.");
		} catch (SQLException e) {
			System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getMessage());
		} catch (ClassNotFoundException e) {
			System.out.println("Impossible de se connecter à la base de données (driver JDBC non disponible)");
		}
		this.tableData.updateUI();
	}
	
	/**
	 * Indique si une case est éditable
	 * @param row		: ligne de la case
	 * @param column	: colonne de la case
	 */
	@Override
	public boolean isCellEditable(int row, int column){
		if (row==0) {
			if (column!=THEME_COL) return false;
		}
		return true;
	}
}
